1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.primitives;
18  
19  import static java.lang.Long.MAX_VALUE;
20  import static java.lang.Long.MIN_VALUE;
21  
22  import com.google.common.annotations.GwtCompatible;
23  import com.google.common.base.Converter;
24  import com.google.common.collect.testing.Helpers;
25  
26  import junit.framework.TestCase;
27  
28  import java.math.BigInteger;
29  import java.util.Arrays;
30  import java.util.Collection;
31  import java.util.Collections;
32  import java.util.Comparator;
33  import java.util.List;
34  import java.util.Random;
35  
36  /**
37   * Unit test for {@link Longs}.
38   *
39   * @author Kevin Bourrillion
40   */
41  @GwtCompatible(emulated = true)
42  @SuppressWarnings("cast") // redundant casts are intentional and harmless
43  public class LongsTest extends TestCase {
44    private static final long[] EMPTY = {};
45    private static final long[] ARRAY1 = {(long) 1};
46    private static final long[] ARRAY234
47        = {(long) 2, (long) 3, (long) 4};
48  
49    private static final long[] VALUES =
50        { MIN_VALUE, (long) -1, (long) 0, (long) 1, MAX_VALUE };
51  
52    public void testCompare() {
53      for (long x : VALUES) {
54        for (long y : VALUES) {
55          // note: spec requires only that the sign is the same
56          assertEquals(x + ", " + y,
57                       Long.valueOf(x).compareTo(y),
58                       Longs.compare(x, y));
59        }
60      }
61    }
62  
63    public void testContains() {
64      assertFalse(Longs.contains(EMPTY, (long) 1));
65      assertFalse(Longs.contains(ARRAY1, (long) 2));
66      assertFalse(Longs.contains(ARRAY234, (long) 1));
67      assertTrue(Longs.contains(new long[] {(long) -1}, (long) -1));
68      assertTrue(Longs.contains(ARRAY234, (long) 2));
69      assertTrue(Longs.contains(ARRAY234, (long) 3));
70      assertTrue(Longs.contains(ARRAY234, (long) 4));
71    }
72  
73    public void testIndexOf() {
74      assertEquals(-1, Longs.indexOf(EMPTY, (long) 1));
75      assertEquals(-1, Longs.indexOf(ARRAY1, (long) 2));
76      assertEquals(-1, Longs.indexOf(ARRAY234, (long) 1));
77      assertEquals(0, Longs.indexOf(
78          new long[] {(long) -1}, (long) -1));
79      assertEquals(0, Longs.indexOf(ARRAY234, (long) 2));
80      assertEquals(1, Longs.indexOf(ARRAY234, (long) 3));
81      assertEquals(2, Longs.indexOf(ARRAY234, (long) 4));
82      assertEquals(1, Longs.indexOf(
83          new long[] { (long) 2, (long) 3, (long) 2, (long) 3 },
84          (long) 3));
85    }
86  
87    public void testIndexOf_arrayTarget() {
88      assertEquals(0, Longs.indexOf(EMPTY, EMPTY));
89      assertEquals(0, Longs.indexOf(ARRAY234, EMPTY));
90      assertEquals(-1, Longs.indexOf(EMPTY, ARRAY234));
91      assertEquals(-1, Longs.indexOf(ARRAY234, ARRAY1));
92      assertEquals(-1, Longs.indexOf(ARRAY1, ARRAY234));
93      assertEquals(0, Longs.indexOf(ARRAY1, ARRAY1));
94      assertEquals(0, Longs.indexOf(ARRAY234, ARRAY234));
95      assertEquals(0, Longs.indexOf(
96          ARRAY234, new long[] { (long) 2, (long) 3 }));
97      assertEquals(1, Longs.indexOf(
98          ARRAY234, new long[] { (long) 3, (long) 4 }));
99      assertEquals(1, Longs.indexOf(ARRAY234, new long[] { (long) 3 }));
100     assertEquals(2, Longs.indexOf(ARRAY234, new long[] { (long) 4 }));
101     assertEquals(1, Longs.indexOf(new long[] { (long) 2, (long) 3,
102         (long) 3, (long) 3, (long) 3 },
103         new long[] { (long) 3 }
104     ));
105     assertEquals(2, Longs.indexOf(
106         new long[] { (long) 2, (long) 3, (long) 2,
107             (long) 3, (long) 4, (long) 2, (long) 3},
108         new long[] { (long) 2, (long) 3, (long) 4}
109     ));
110     assertEquals(1, Longs.indexOf(
111         new long[] { (long) 2, (long) 2, (long) 3,
112             (long) 4, (long) 2, (long) 3, (long) 4},
113         new long[] { (long) 2, (long) 3, (long) 4}
114     ));
115     assertEquals(-1, Longs.indexOf(
116         new long[] { (long) 4, (long) 3, (long) 2},
117         new long[] { (long) 2, (long) 3, (long) 4}
118     ));
119   }
120 
121   public void testLastIndexOf() {
122     assertEquals(-1, Longs.lastIndexOf(EMPTY, (long) 1));
123     assertEquals(-1, Longs.lastIndexOf(ARRAY1, (long) 2));
124     assertEquals(-1, Longs.lastIndexOf(ARRAY234, (long) 1));
125     assertEquals(0, Longs.lastIndexOf(
126         new long[] {(long) -1}, (long) -1));
127     assertEquals(0, Longs.lastIndexOf(ARRAY234, (long) 2));
128     assertEquals(1, Longs.lastIndexOf(ARRAY234, (long) 3));
129     assertEquals(2, Longs.lastIndexOf(ARRAY234, (long) 4));
130     assertEquals(3, Longs.lastIndexOf(
131         new long[] { (long) 2, (long) 3, (long) 2, (long) 3 },
132         (long) 3));
133   }
134 
135   public void testMax_noArgs() {
136     try {
137       Longs.max();
138       fail();
139     } catch (IllegalArgumentException expected) {
140     }
141   }
142 
143   public void testMax() {
144     assertEquals(MIN_VALUE, Longs.max(MIN_VALUE));
145     assertEquals(MAX_VALUE, Longs.max(MAX_VALUE));
146     assertEquals((long) 9, Longs.max(
147         (long) 8, (long) 6, (long) 7,
148         (long) 5, (long) 3, (long) 0, (long) 9));
149   }
150 
151   public void testMin_noArgs() {
152     try {
153       Longs.min();
154       fail();
155     } catch (IllegalArgumentException expected) {
156     }
157   }
158 
159   public void testMin() {
160     assertEquals(MIN_VALUE, Longs.min(MIN_VALUE));
161     assertEquals(MAX_VALUE, Longs.min(MAX_VALUE));
162     assertEquals((long) 0, Longs.min(
163         (long) 8, (long) 6, (long) 7,
164         (long) 5, (long) 3, (long) 0, (long) 9));
165   }
166 
167   public void testConcat() {
168     assertTrue(Arrays.equals(EMPTY, Longs.concat()));
169     assertTrue(Arrays.equals(EMPTY, Longs.concat(EMPTY)));
170     assertTrue(Arrays.equals(EMPTY, Longs.concat(EMPTY, EMPTY, EMPTY)));
171     assertTrue(Arrays.equals(ARRAY1, Longs.concat(ARRAY1)));
172     assertNotSame(ARRAY1, Longs.concat(ARRAY1));
173     assertTrue(Arrays.equals(ARRAY1, Longs.concat(EMPTY, ARRAY1, EMPTY)));
174     assertTrue(Arrays.equals(
175         new long[] {(long) 1, (long) 1, (long) 1},
176         Longs.concat(ARRAY1, ARRAY1, ARRAY1)));
177     assertTrue(Arrays.equals(
178         new long[] {(long) 1, (long) 2, (long) 3, (long) 4},
179         Longs.concat(ARRAY1, ARRAY234)));
180   }
181 
182   private static void assertByteArrayEquals(byte[] expected, byte[] actual) {
183     assertTrue(
184         "Expected: " + Arrays.toString(expected) + ", but got: " + Arrays.toString(actual),
185         Arrays.equals(expected, actual));
186   }
187 
188   public void testToByteArray() {
189     assertByteArrayEquals(
190         new byte[] {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19},
191         Longs.toByteArray(0x1213141516171819L));
192     assertByteArrayEquals(
193         new byte[] {
194             (byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
195             (byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88},
196         Longs.toByteArray(0xFFEEDDCCBBAA9988L));
197   }
198 
199   public void testFromByteArray() {
200     assertEquals(0x1213141516171819L, Longs.fromByteArray(
201         new byte[] {0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x33}));
202     assertEquals(0xFFEEDDCCBBAA9988L, Longs.fromByteArray(
203         new byte[] {
204             (byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
205             (byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88}));
206 
207     try {
208       Longs.fromByteArray(new byte[Longs.BYTES - 1]);
209       fail();
210     } catch (IllegalArgumentException expected) {
211     }
212   }
213 
214   public void testFromBytes() {
215     assertEquals(0x1213141516171819L, Longs.fromBytes(
216         (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15,
217         (byte) 0x16, (byte) 0x17, (byte) 0x18, (byte) 0x19));
218     assertEquals(0xFFEEDDCCBBAA9988L, Longs.fromBytes(
219         (byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC,
220         (byte) 0xBB, (byte) 0xAA, (byte) 0x99, (byte) 0x88));
221   }
222 
223   public void testByteArrayRoundTrips() {
224     Random r = new Random(5);
225     byte[] b = new byte[Longs.BYTES];
226 
227     // total overkill, but, it takes 0.1 sec so why not...
228     for (int i = 0; i < 10000; i++) {
229       long num = r.nextLong();
230       assertEquals(num, Longs.fromByteArray(Longs.toByteArray(num)));
231 
232       r.nextBytes(b);
233       long value = Longs.fromByteArray(b);
234       assertTrue("" + value, Arrays.equals(b, Longs.toByteArray(value)));
235     }
236   }
237 
238   public void testEnsureCapacity() {
239     assertSame(EMPTY, Longs.ensureCapacity(EMPTY, 0, 1));
240     assertSame(ARRAY1, Longs.ensureCapacity(ARRAY1, 0, 1));
241     assertSame(ARRAY1, Longs.ensureCapacity(ARRAY1, 1, 1));
242     assertTrue(Arrays.equals(
243         new long[] {(long) 1, (long) 0, (long) 0},
244         Longs.ensureCapacity(ARRAY1, 2, 1)));
245   }
246 
247   public void testEnsureCapacity_fail() {
248     try {
249       Longs.ensureCapacity(ARRAY1, -1, 1);
250       fail();
251     } catch (IllegalArgumentException expected) {
252     }
253     try {
254       // notice that this should even fail when no growth was needed
255       Longs.ensureCapacity(ARRAY1, 1, -1);
256       fail();
257     } catch (IllegalArgumentException expected) {
258     }
259   }
260 
261   public void testJoin() {
262     assertEquals("", Longs.join(",", EMPTY));
263     assertEquals("1", Longs.join(",", ARRAY1));
264     assertEquals("1,2", Longs.join(",", (long) 1, (long) 2));
265     assertEquals("123",
266         Longs.join("", (long) 1, (long) 2, (long) 3));
267   }
268 
269   public void testLexicographicalComparator() {
270     List<long[]> ordered = Arrays.asList(
271         new long[] {},
272         new long[] {MIN_VALUE},
273         new long[] {MIN_VALUE, MIN_VALUE},
274         new long[] {MIN_VALUE, (long) 1},
275         new long[] {(long) 1},
276         new long[] {(long) 1, MIN_VALUE},
277         new long[] {MAX_VALUE, MAX_VALUE - (long) 1},
278         new long[] {MAX_VALUE, MAX_VALUE},
279         new long[] {MAX_VALUE, MAX_VALUE, MAX_VALUE});
280 
281     Comparator<long[]> comparator = Longs.lexicographicalComparator();
282     Helpers.testComparator(comparator, ordered);
283   }
284 
285   public void testToArray() {
286     // need explicit type parameter to avoid javac warning!?
287     List<Long> none = Arrays.<Long>asList();
288     assertTrue(Arrays.equals(EMPTY, Longs.toArray(none)));
289 
290     List<Long> one = Arrays.asList((long) 1);
291     assertTrue(Arrays.equals(ARRAY1, Longs.toArray(one)));
292 
293     long[] array = {(long) 0, (long) 1, 0x0FF1C1AL};
294 
295     List<Long> three = Arrays.asList((long) 0, (long) 1, 0x0FF1C1AL);
296     assertTrue(Arrays.equals(array, Longs.toArray(three)));
297 
298     assertTrue(Arrays.equals(array, Longs.toArray(Longs.asList(array))));
299   }
300 
301   public void testToArray_threadSafe() {
302     for (int delta : new int[] { +1, 0, -1 }) {
303       for (int i = 0; i < VALUES.length; i++) {
304         List<Long> list = Longs.asList(VALUES).subList(0, i);
305         Collection<Long> misleadingSize =
306             Helpers.misleadingSizeCollection(delta);
307         misleadingSize.addAll(list);
308         long[] arr = Longs.toArray(misleadingSize);
309         assertEquals(i, arr.length);
310         for (int j = 0; j < i; j++) {
311           assertEquals(VALUES[j], arr[j]);
312         }
313       }
314     }
315   }
316 
317   public void testToArray_withNull() {
318     List<Long> list = Arrays.asList((long) 0, (long) 1, null);
319     try {
320       Longs.toArray(list);
321       fail();
322     } catch (NullPointerException expected) {
323     }
324   }
325 
326   public void testToArray_withConversion() {
327     long[] array = {(long) 0, (long) 1, (long) 2};
328 
329     List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
330     List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
331     List<Integer> ints = Arrays.asList(0, 1, 2);
332     List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
333     List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
334     List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
335 
336     assertTrue(Arrays.equals(array, Longs.toArray(bytes)));
337     assertTrue(Arrays.equals(array, Longs.toArray(shorts)));
338     assertTrue(Arrays.equals(array, Longs.toArray(ints)));
339     assertTrue(Arrays.equals(array, Longs.toArray(floats)));
340     assertTrue(Arrays.equals(array, Longs.toArray(longs)));
341     assertTrue(Arrays.equals(array, Longs.toArray(doubles)));
342   }
343 
344   public void testAsList_isAView() {
345     long[] array = {(long) 0, (long) 1};
346     List<Long> list = Longs.asList(array);
347     list.set(0, (long) 2);
348     assertTrue(Arrays.equals(new long[] {(long) 2, (long) 1}, array));
349     array[1] = (long) 3;
350     assertEquals(Arrays.asList((long) 2, (long) 3), list);
351   }
352 
353   public void testAsList_toArray_roundTrip() {
354     long[] array = { (long) 0, (long) 1, (long) 2 };
355     List<Long> list = Longs.asList(array);
356     long[] newArray = Longs.toArray(list);
357 
358     // Make sure it returned a copy
359     list.set(0, (long) 4);
360     assertTrue(Arrays.equals(
361         new long[] { (long) 0, (long) 1, (long) 2 }, newArray));
362     newArray[1] = (long) 5;
363     assertEquals((long) 1, (long) list.get(1));
364   }
365 
366   // This test stems from a real bug found by andrewk
367   public void testAsList_subList_toArray_roundTrip() {
368     long[] array = { (long) 0, (long) 1, (long) 2, (long) 3 };
369     List<Long> list = Longs.asList(array);
370     assertTrue(Arrays.equals(new long[] { (long) 1, (long) 2 },
371         Longs.toArray(list.subList(1, 3))));
372     assertTrue(Arrays.equals(new long[] {},
373         Longs.toArray(list.subList(2, 2))));
374   }
375 
376   public void testAsListEmpty() {
377     assertSame(Collections.emptyList(), Longs.asList(EMPTY));
378   }
379 
380   public void testStringConverter_convert() {
381     Converter<String, Long> converter = Longs.stringConverter();
382     assertEquals((Long) 1L, converter.convert("1"));
383     assertEquals((Long) 0L, converter.convert("0"));
384     assertEquals((Long) (-1L), converter.convert("-1"));
385     assertEquals((Long) 255L, converter.convert("0xff"));
386     assertEquals((Long) 255L, converter.convert("0xFF"));
387     assertEquals((Long) (-255L), converter.convert("-0xFF"));
388     assertEquals((Long) 255L, converter.convert("#0000FF"));
389     assertEquals((Long) 438L, converter.convert("0666"));
390   }
391 
392   public void testStringConverter_convertError() {
393     try {
394       Longs.stringConverter().convert("notanumber");
395       fail();
396     } catch (NumberFormatException expected) {
397     }
398   }
399 
400   public void testStringConverter_nullConversions() {
401     assertNull(Longs.stringConverter().convert(null));
402     assertNull(Longs.stringConverter().reverse().convert(null));
403   }
404 
405   public void testStringConverter_reverse() {
406     Converter<String, Long> converter = Longs.stringConverter();
407     assertEquals("1", converter.reverse().convert(1L));
408     assertEquals("0", converter.reverse().convert(0L));
409     assertEquals("-1", converter.reverse().convert(-1L));
410     assertEquals("255", converter.reverse().convert(0xffL));
411     assertEquals("255", converter.reverse().convert(0xFFL));
412     assertEquals("-255", converter.reverse().convert(-0xFFL));
413     assertEquals("438", converter.reverse().convert(0666L));
414   }
415 
416   public void testTryParse() {
417     tryParseAndAssertEquals(0L, "0");
418     tryParseAndAssertEquals(0L, "-0");
419     tryParseAndAssertEquals(1L, "1");
420     tryParseAndAssertEquals(-1L, "-1");
421     tryParseAndAssertEquals(8900L, "8900");
422     tryParseAndAssertEquals(-8900L, "-8900");
423     tryParseAndAssertEquals(MAX_VALUE, Long.toString(MAX_VALUE));
424     tryParseAndAssertEquals(MIN_VALUE, Long.toString(MIN_VALUE));
425     assertNull(Longs.tryParse(""));
426     assertNull(Longs.tryParse("-"));
427     assertNull(Longs.tryParse("+1"));
428     assertNull(Longs.tryParse("999999999999999999999999"));
429     assertNull("Max long + 1",
430         Longs.tryParse(BigInteger.valueOf(MAX_VALUE).add(BigInteger.ONE).toString()));
431     assertNull("Max long * 10",
432         Longs.tryParse(BigInteger.valueOf(MAX_VALUE).multiply(BigInteger.TEN).toString()));
433     assertNull("Min long - 1",
434         Longs.tryParse(BigInteger.valueOf(MIN_VALUE).subtract(BigInteger.ONE).toString()));
435     assertNull("Min long * 10",
436         Longs.tryParse(BigInteger.valueOf(MIN_VALUE).multiply(BigInteger.TEN).toString()));
437     assertNull(Longs.tryParse("\u0662\u06f3"));
438   }
439 
440   /**
441    * Applies {@link Longs#tryParse(String)} to the given string and asserts that
442    * the result is as expected.
443    */
444   private static void tryParseAndAssertEquals(Long expected, String value) {
445     assertEquals(expected, Longs.tryParse(value));
446   }
447 }
448